﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YJKArchUtils.Utils;

namespace YJKRevitWallModule.WallModule.CreateWall
{
	public class WallTypeManager
	{
		public WallTypeManager(Autodesk.Revit.DB.Document inputDoc, List<WallType> lstInputWallTypes, ExternalCommandData commandData)
		{
			this.m_commandData = commandData;
			this.m_doc = inputDoc;
			this.m_lstWallTypes = lstInputWallTypes;
		}

		public void SetUseData(UseData inputData)
		{
			this.m_useData = inputData;
		}

		public WallType CreateNewWallType()
		{
			WallType wallType = null;
			List<WallType> allWallTypes = this.GetAllWallTypes();
			string text = this.CreateNewWallTypeName();
			foreach (WallType wallType2 in allWallTypes)
			{
				if (wallType2.Name == text)
				{
					if (this.IsNeedChangeMaterial(wallType2))
					{
						wallType = wallType2;
						break;
					}
					return wallType2;
				}
			}
			IDictionary<int, CompoundStructureError> dictionary = null;
			IDictionary<int, int> dictionary2 = null;
			Transaction transaction = new Transaction(this.m_doc, "Create New WallType");
			transaction.Start();
			try
			{
				if (wallType == null)
				{
					foreach (WallType wallType3 in this.m_lstWallTypes)
					{
                        if (wallType3.Kind == WallKind.Basic && 
                            wallType3.GetCompoundStructure() != null && 
                            wallType3.GetCompoundStructure().IsValid(this.m_doc, out dictionary, out dictionary2))
						{
							wallType = (wallType3.Duplicate(text) as WallType);
							break;
						}
					}
				}

				List<CompoundStructureLayer> list = new List<CompoundStructureLayer>();
				if (this.m_useData.strLeftKeepWarmWidth != "0")
				{
                    CompoundStructureLayer item = new CompoundStructureLayer(Common.MMToFeet(double.Parse(this.m_useData.strLeftKeepWarmWidth)), (MaterialFunctionAssignment)3, this.m_useData.strLeftKeepWarmId);
					list.Add(item);
				}

                CompoundStructureLayer item2 = new CompoundStructureLayer(Common.MMToFeet(double.Parse(this.m_useData.strWallWidth)), (MaterialFunctionAssignment)1, this.GetMaterialId());
				list.Add(item2);
				if (this.m_useData.strRightKeepWarmWidth != "0")
				{
                    CompoundStructureLayer item3 = new CompoundStructureLayer(Common.MMToFeet(double.Parse(this.m_useData.strRightKeepWarmWidth)), (MaterialFunctionAssignment)3, this.m_useData.strRightKeepWarmId);
					list.Add(item3);
				}
				CompoundStructure compoundStructure;
				if (list.Count == 1 && 2015 == Convert.ToInt32(this.m_commandData.Application.Application.VersionNumber))
				{
                    compoundStructure = CompoundStructure.CreateSingleLayerCompoundStructure((MaterialFunctionAssignment)1, Common.MMToFeet(double.Parse(this.m_useData.strWallWidth)), this.GetMaterialId());
				}
				else
				{
					compoundStructure = wallType.GetCompoundStructure();
					compoundStructure.SetLayers(list);
				}
				int i = 0;
				int num = -1;
				int num2 = -1;
				while (i < list.Count)
				{
					if ((int)list[i].Function == 1)
					{
						if (num == -1)
						{
							num = i;
						}
						num2 = i;
					}
					i++;
				}
				if (num == -1)
				{
					compoundStructure.SetNumberOfShellLayers((Autodesk.Revit.DB.ShellLayerType)0, 0);
					compoundStructure.SetNumberOfShellLayers((Autodesk.Revit.DB.ShellLayerType)1, 0);
				}
				else if (list.Count == 2)
				{
					if ((int)list[1].Function == 1)
					{
						compoundStructure.SetNumberOfShellLayers((Autodesk.Revit.DB.ShellLayerType)0, num - 1);
						compoundStructure.SetNumberOfShellLayers((Autodesk.Revit.DB.ShellLayerType)1, list.Count - num);
					}
					else
					{
						compoundStructure.SetNumberOfShellLayers((Autodesk.Revit.DB.ShellLayerType)0, list.Count - num - 1);
						compoundStructure.SetNumberOfShellLayers((Autodesk.Revit.DB.ShellLayerType)1, num);
					}
				}
				else if (num == num2)
				{
					compoundStructure.SetNumberOfShellLayers((Autodesk.Revit.DB.ShellLayerType)0, num);
					compoundStructure.SetNumberOfShellLayers((Autodesk.Revit.DB.ShellLayerType)1, list.Count - num - 1);
				}
				wallType.SetCompoundStructure(compoundStructure);
				transaction.Commit();
			}
			catch (Exception)
			{
				transaction.RollBack();
				return null;
			}
			return wallType;
		}

		private bool IsNeedChangeMaterial(WallType inputType)
		{
			IList<CompoundStructureLayer> layers = inputType.GetCompoundStructure().GetLayers();
			for (int i = 0; i < layers.Count; i++)
			{
				if ((int)layers[i].Function == 3)
				{
					if (i == 0 && layers[i].MaterialId != this.m_useData.strLeftKeepWarmId)
					{
						return true;
					}
					if (i == 1 && layers[i].MaterialId != this.m_useData.strRightKeepWarmId)
					{
						return true;
					}
					if (i == 2 && layers[i].MaterialId != this.m_useData.strRightKeepWarmId)
					{
						return true;
					}
				}
			}
			return false;
		}

		private ElementId GetMaterialId()
		{
			List<Material> allMaterial = Common.GetAllMaterial(this.m_doc);
			ElementId elementId = null;
			foreach (Material material in allMaterial)
			{
				if (this.m_useData.strMaterial2FillName.Key == material.Name)
				{
					elementId = material.Id;
					break;
				}
			}
			if (null == elementId)
			{
				Material material2 = allMaterial[0].Duplicate(this.m_useData.strMaterial2FillName.Key);
				Common.SetMaterialByFillPattern(this.m_doc, this.m_useData.strMaterial2FillName.Value, ref material2, true);
				elementId = material2.Id;
			}
			return elementId;
		}

		private string CreateNewWallTypeName()
		{
			string result = string.Empty;
			if (this.m_useData.strLeftKeepWarmWidth != "0" && this.m_useData.strRightKeepWarmWidth != "0")
			{
				result = string.Concat(new string[]
				{
					this.m_useData.strPurpose,
					"-",
					this.m_useData.strLeftKeepWarmWidth,
					"+",
					this.m_useData.strWallWidth,
					"+",
					this.m_useData.strRightKeepWarmWidth,
					"-",
					this.m_useData.strMaterial2FillName.Key
				});
			}
			else if (this.m_useData.strLeftKeepWarmWidth != "0")
			{
				result = string.Concat(new string[]
				{
					this.m_useData.strPurpose,
					"-",
					this.m_useData.strLeftKeepWarmWidth,
					"+",
					this.m_useData.strWallWidth,
					"-",
					this.m_useData.strMaterial2FillName.Key
				});
			}
			else if (this.m_useData.strRightKeepWarmWidth != "0")
			{
				result = string.Concat(new string[]
				{
					this.m_useData.strPurpose,
					"-",
					this.m_useData.strWallWidth,
					"+",
					this.m_useData.strRightKeepWarmWidth,
					"-",
					this.m_useData.strMaterial2FillName.Key
				});
			}
			else
			{
				result = string.Concat(new string[]
				{
					this.m_useData.strPurpose,
					"-",
					this.m_useData.strWallWidth,
					"-",
					this.m_useData.strMaterial2FillName.Key
				});
			}
			return result;
		}

		private List<WallType> GetAllWallTypes()
		{
			List<WallType> list = new List<WallType>();
			foreach (Element element in new FilteredElementCollector(this.m_doc).OfClass(typeof(WallType)).ToElements())
			{
				WallType wallType = element as WallType;
				if (wallType != null)
				{
					list.Add(wallType);
				}
			}
			return list;
		}

		public UseData m_useData;

		private ExternalCommandData m_commandData;

		private Document m_doc;

		private List<WallType> m_lstWallTypes = new List<WallType>();
	}
}
